/*
 * Created on 2005/06/12
 * Author aki@www.xucker.jpn.org
 * License Apache2.0 or Common Public License
 */
package jp.sourceforge.akjrcp.ui.draw2d;

import org.eclipse.draw2d.Graphics;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.GC;

import java.util.ArrayList;
import java.util.List;

/**
 * 
 *
 */
public class WrapTextPainter {

private int width;
private Font font;
public static Font defaultFont=new Font(null,"MS Gothic",24,SWT.NONE);;


private String text;
String[] texts;
int[] styles;
int[] returnPoint;
byte[] charWidths;


private char splitchars[]={'\n',' ',':',';','.',','};

private boolean wrap=true;

private boolean reanalyze=true;
private int stringHeight;

//public static final int UNDERLINE=1;
//public static final int BACKGROUND=2;

public WrapTextPainter(int width,Font font){

    this.width=width;
    this.font=font;
}


public void paint(GC g,int drawX,int drawY) {
    
    if(reanalyze){
        g.setFont(font);
        charWidths=toCharByte(g,getText());
        returnPoint=splitLine(g);
        
        reanalyze=false;
    }
 
    
    g.setFont(font);
    if(texts!=null){
    int dx=drawX;
    int dy=drawY;
    
    int index=0;
    for(int j=0;j<texts.length;j++){
        if(isReturn(j)){
            dx=drawX;
            dy+=stringHeight;
        }
        
        if(!texts[j].equals("\n")){
            int length=toWordLength(index,texts[j].length());
            g.drawString(texts[j],dx,dy);
            //g.drawLine(dx,dy+height,dx+length,dy+height);
            dx+=length;
        }
        
        index+=texts[j].length();
    
}
    }
}

/**
 * @return
 */
private String getText() {
return text;
}


public int getClickIndex(int x,int y){
    int last=-1;
    int cy=0;
    if(y>0){
        cy=y/stringHeight;
    }
    int sx=0;
    int dx=0;
    if(cy>returnPoint.length){
        return -1;
    }
    if(cy>0){
        if(returnPoint.length>=cy){
            sx=returnPoint[cy-1];
            if(returnPoint.length>cy){
                last=returnPoint[cy];
            }
        }
    }else{
        if(returnPoint.length>0){
            last=returnPoint[0];
        }
    }
    
    for(int i=sx;i<texts.length;i++){
        if(i==last){
            break;
        }
        int length=toWordLength(i);
        if(x>=dx&& x<=dx+length){
            return i;
        }else{
            dx+=length;
        }
    }
    
    
    return -1;
}



public void setText(String text){
    this.text=text;
    this.texts=splitText(text);
    reanalyze=true;
    
}

public String[] splitText(String text){
    List list=new ArrayList();
    StringBuffer buffer=new StringBuffer();
    for(int i=0;i<text.length();i++){
        char ch=text.charAt(i);
        boolean isSplit=false;
        for(int j=0;j<splitchars.length;j++){
           
            if(ch==splitchars[j]){
                isSplit=true;
                break;
            }
            
        }
        if(isSplit){
            if(buffer.length()>0){
                list.add(buffer.toString());
                list.add(""+ch);
                buffer=new StringBuffer();
            }else{
                list.add(""+ch);
            }
            
        
        }else{
                buffer.append(ch);
            }
    }
    if(buffer.length()>0){
        list.add(buffer.toString());
    }
    /*
    for(int i=0;i<list.size();i++){
        log.info(list.get(i));
    }*/
    
    return (String[]) list.toArray(new String[list.size()]);
}

public byte[] toCharByte(GC gc,String text){
	    byte[] bytes=new byte[text.length()];
	    for(int i=0;i<bytes.length;i++){
	        if(text.charAt(i)=='\n'){
	        bytes[i]=0;
	        }else{
	        bytes[i]=(byte)gc.stringExtent(""+text.charAt(i)).x;
	     //   log.info"+text.charAt(i)+"="+bytes[i]);
	        }
	    }
	    return bytes;
	}


private int toWordLength(int index){
    int start=0;
    for(int i=0;i<index;i++){
        if(i<texts.length){
            start+=texts[i].length();
        }
    }
    return toWordLength(start,texts[index].length());
}

	private int toWordLength(int start,int length){
	    int result=0;
	    for(int i=start;i<start+length;i++){
	        result+=charWidths[i];
	    }
	    return result;
	}
	
	public int[] splitLine(GC gc){
	  
	    List returnList=new ArrayList();
	    
	    int dx=0;
	    int dy=0;
	    stringHeight = gc.getFontMetrics().getHeight();
        int index=0;
	    for(int j=0;j<texts.length;j++){
	        
	        if(!texts[j].equals("\n")){
	            int length=toWordLength(index,texts[j].length());
	            //log.info"+dx+length+","+width);
	            if(wrap && dx+length>width){
	                //wrap
	                returnList.add(new Integer(j));
	                dx=0;
		            dy+=stringHeight;
	            }
	           
	            dx+=length;
	        }else{
	            dx=0;
	            dy+=stringHeight;
	            returnList.add(new Integer(j));
	        }
	        index+=texts[j].length();
	    
	}
	    
	    
	    
	    Integer[] integers=(Integer[]) returnList.toArray(new Integer[returnList.size()]);
	    int ret[]=new int[integers.length];
	    for(int i=0;i<ret.length;i++){
	        ret[i]=integers[i].intValue();
	    }
	    return ret;
	}
	
	public String getWord(int index){
	    return texts[index];
	}
	public int countWord(){
	    return texts.length;
	}
	
	public boolean isReturn(int index){
	    for(int i=0;i<returnPoint.length;i++){
	        if(returnPoint[i]==index){
	            return true;
	        }
	    }
	    return false;
	}
}
